//==============================================================================
//
// Title:       SetSignalGenerator.c
// Purpose:     A short description of the implementation.
//
// Created on:  2012-5-11 at 11:12:01 by luh.
// Copyright:   dafda. All Rights Reserved.
//
//==============================================================================

//==============================================================================
// Include files
#include "RFBB.h"
#include <utility.h> 
#include "SetSignalGenerator.h"
#include <formatio.h> 

ViSession   g_hSignalGenerator = 0;

// -----------------------------------------------------------------------
// Function:   SignalGeneratorInitThreadFunc
// Purpose:    Init signal generator in thread
//
int CVICALLBACK SignalGeneratorInitThreadFunc( void* functionData )
{
   int iReturn = 0;
   double dDbgTimer = 0.0; // For TUWF_DEBUG_PRINT
   
   TUWF_DEBUG_PRINT("SG Init start %.2f\n");
   iReturn = InitSignalGenerator();
   TUWF_DEBUG_PRINT("SG Init done. %.2f\n");

   return iReturn; 
}


// -----------------------------------------------------------------------
// Function:   SignalGeneratorBerSetupThreadFunc
// Purpose:    setup signal generator in thread for BER measurement
//
int CVICALLBACK SignalGeneratorBerSetupThreadFunc( void* functionData )
{
   int iReturn = 0;
   int error = 0;
   unsigned long int iScramblingCode = 0;
   char errMsg[256] = {'\0'};
   char* pszTempBuff = 0;
   
   error = RegReadULong( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                           "ScramblingCode", &iScramblingCode, 0 );
   if( error ) {
      pszTempBuff = GetGeneralErrorString(error);
      sprintf(errMsg, "ESG\\ScramblingCode - %s - use default", pszTempBuff);
      EELog_INEventLogLogEvent( g_hEventLog, NULL, errMsg);
      error = 0;
   }
   iReturn = SetupEsgSignalGeneration( iScramblingCode );
   
   return iReturn; 
}


// -----------------------------------------------------------------------
// Function:   InitSignalGenerator
// Purpose:    get instrument address from registry and init
//
int InitSignalGenerator( void )
{
   int error = 0;
   unsigned int size = 0;
   char* pszTempBuff = 0;
   char kszSubKey[] = {"SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG"};
   char errMsg[256] = {'\0'};
   char szLogMsg[BUF_SIZE_SMALL] = {'\0'};
   unsigned char szDeviceAddress[BUF_SIZE_SMALL] = {'\0'};
   int iReturn = 0;
   
   
   EELog_INEventLogLogEvent (g_hEventLog, NULL, "Signal generator initialisation started ...");
   error = RegReadString( REGKEY_HKLM, kszSubKey, "DeviceAddress", 
                           szDeviceAddress, sizeof(szDeviceAddress), &size );
   if( error )
   {
      pszTempBuff = GetGeneralErrorString(error);
      sprintf(errMsg, "ESG\\DeviceAddress - %s", pszTempBuff);
      goto Error;
   }  
   
   error = hpESG_init ((ViRsrc)szDeviceAddress, VI_FALSE, VI_FALSE, &g_hSignalGenerator);
   if(error != 0) {
      sprintf(errMsg, "ESG initialization failed ! Error code: %ld", error);
      if(error > 0) {
         error -= 2*error;
      }
      goto Error;
   }  
   
Error:
   sprintf( szLogMsg, "Leaving signal generator initialisation, return %d...", error );
   EELog_INEventLogLogEvent( g_hEventLog, NULL, szLogMsg );
   
   if( error < 0 ) {
      EELog_INEventLogLogEvent (g_hEventLog, NULL, errMsg);
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }
   
   return error;
}

// -----------------------------------------------------------------------
// Function:   WaitForOPC
// Purpose:    Waits until esg has completed its operation
//
int WaitForOPC()
{
   ViBoolean bReady = VI_FALSE;
   
   while( bReady == VI_FALSE )
   {
      hpESG_opc_Q (g_hSignalGenerator, &bReady);
      Delay(0.25);
   }
   return 0;
} 

// SetFrequency ?
// SetAmplitude ?

// -----------------------------------------------------------------------
// Function:   SetupEsgSignalRxWcdma
// Purpose:    Set ESG signal generation for real-time uplink signal  
// Parameters: int iScramblingCode
//             int iTimingOffset
//  
int SetupEsgSignalRxWcdma( int iScramblingCode )
{
   int error = 0;
   //int iReturn = 0;
   ErrMsg errMsg = {'\0'};
   ViStatus viStatus = 0;
   
   EELog_INEventLogLogEvent( g_hEventLog, NULL, 
                              "Setting ESG signal generator for RX calibration...");

   // Init multicarrier table:
   //esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK DOWN;*OPC?"));  // ????
   //WaitForOPC();
   
   // *WAI; ????
   
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET MCARrier"));
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL INIT,PPSCH,-2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,-2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,PPSCH,2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,2.5E+6,0.0") );
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL INIT,PPSCH,0.0,0.0") );
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,0.0,0.0") ); 

   
   // generate a W-CDMA signal based on the current values in the W-CDMA channel table
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:TABL:APPL;*OPC?") );
   WaitForOPC();

   // WCDMA ON
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:STAT ON;*OPC?") );
   EELog_INEventLogLogEvent( g_hEventLog, NULL, "Start OPC query...");
   WaitForOPC();
   EELog_INEventLogLogEvent( g_hEventLog, NULL, "Done!");
   
   hpESG_ModulationSetOn( g_hSignalGenerator, VI_TRUE );
   
Error:
   if( error < 0 ) {
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }
   
   return error;
} 

// -----------------------------------------------------------------------
// Function:   SetupEsgSignalGeneration
// Purpose:    Set ESG signal generation for real-time downlink signal  
// Parameters: int iTimingOffset
//  
int SetupEsgSignalBbgDLWcdma( int iScramblingCode)
{
   int error = 0;
   int iTimingOffSet = 0;
   ErrMsg errMsg = {'\0'};
   unsigned char szRegString[255] = {'\0'}; 
   unsigned int uiStringSize = 0;
   char* pszTempBuff = 0;
   
   ViStatus viStatus = 0;
   ViChar viBuffer[ESG_BUFFER_SIZE];
   
   EELog_INEventLogLogEvent (g_hEventLog, NULL, "# Setting ESG signal generation for Downlink measurement...");
   
   // Setup channeltype: Uplink real-time
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "DL RT...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:LINK DOWN;*OPC?") );
   WaitForOPC();
   // Scrambling code 0 for starters...
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "SCR Code...");
   //esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:DLIN:SCR 0") );
   
  // Timing offset
   error = RegReadULong( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                           "TimingOffset", &iTimingOffSet, 0 );
   if( error ) {
      pszTempBuff = GetGeneralErrorString(error);
      sprintf(errMsg, "ESG\\TimingOffset - %s - use default", pszTempBuff);
      EELog_INEventLogLogEvent( g_hEventLog, NULL, errMsg);
      error = 0;
   }

   // WCDMA state ON
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Wcdma state ON...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "RAD:WCDM:TGPP:BBG:STAT ON;*OPC?") );
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Start OPC query...");
   WaitForOPC();
   Delay(5.0); // 
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Done!");
   
   // Set scrambling code 
   sprintf( viBuffer, ":RAD:WCDM:TGPP:BBG:DLIN:SCR %d", iScramblingCode );
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "SCR Code...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );   
   EELog_INEventLogLogEvent (g_hEventLog, NULL, "ESG setup done.");    
   
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;") );

Error:
   if( error < 0 ) {
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }
   
   return error;
} 


// -----------------------------------------------------------------------
// Function:   SetupEsgSignalGeneration
// Purpose:    Set ESG signal generation for real-time uplink signal  
// Parameters: int iScramblingCode
//             int iTimingOffset
//  
int SetupEsgSignalGeneration( int iScramblingCode )
{
   int error = 0;
   int iTimingOffSet = 0;
   ErrMsg errMsg = {'\0'};
   unsigned char szRegString[255] = {'\0'}; 
   unsigned int uiStringSize = 0;
   char* pszTempBuff = 0;
   
   ViStatus viStatus = 0;
   ViChar viBuffer[ESG_BUFFER_SIZE];
   
   EELog_INEventLogLogEvent (g_hEventLog, NULL, "# Setting ESG signal generation for BER measurement...");
   
   // Setup channeltype: Uplink real-time
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "UL RT...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:LINK UP;*OPC?") );
   WaitForOPC();
   // Scrambling code 0 for starters...
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "SCR Code...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:ULIN:SCR 0") );
   
   // Sync source (SFN_RST|FCLock|ESG)
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Sync source...");
   error = RegReadString( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                  "SyncSource", szRegString, sizeof(szRegString), &uiStringSize );
   if( error ) {
      pszTempBuff = GetGeneralErrorString(error);
      sprintf(errMsg, "ESG\\SyncSource - %s", pszTempBuff);
      goto Error;
   }                   
   
   if( strcmp((char*)szRegString, "SFN0") == 0 ) {
      sprintf( viBuffer, "RAD:WCDM:TGPP:BBG:ULIN:SYNC %s", "SFN_RST" );
      esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
   }
   else if( strcmp((char*)szRegString, "FCLK") == 0 ) {
      // Frame clock interval
      error = RegReadString( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                  "FrameClockInterval", szRegString, sizeof(szRegString), &uiStringSize );
      if( error ) {
         pszTempBuff = GetGeneralErrorString(error);
         sprintf(errMsg, "ESG\\FrameClockInterval - %s", pszTempBuff);
         goto Error;
      }
      sprintf( viBuffer, "RAD:WCDM:TGPP:BBG:ULIN:FCL:INT FCL%s", szRegString );
      esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
      
      esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
      sprintf( viBuffer, "RAD:WCDM:TGPP:BBG:ULIN:SYNC %s", "FCL" );
      esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
      
      // Frame clock polarity (NEG | POS)
      error = RegReadString( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                  "FrameClockPolarity", szRegString, sizeof(szRegString), &uiStringSize );
      if( error ) {
         pszTempBuff = GetGeneralErrorString(error);
         sprintf(errMsg, "ESG\\FrameClockPolarity - %s - use default", pszTempBuff);
         EELog_INEventLogLogEvent( g_hEventLog, NULL, errMsg);
         sprintf( szRegString, "POS" );
         error = 0;
      }
      
      sprintf( viBuffer, ":RAD:WCDM:TGPP:BBG:ULIN:FCL:POL %s", szRegString );
      esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
   }
  
   // Timing offset
   error = RegReadULong( REGKEY_HKLM, "SOFTWARE\\NSN\\SWIFT\\Instruments\\ESG", 
                           "TimingOffset", &iTimingOffSet, 0 );
   if( error ) {
      pszTempBuff = GetGeneralErrorString(error);
      sprintf(errMsg, "ESG\\TimingOffset - %s - use default", pszTempBuff);
      EELog_INEventLogLogEvent( g_hEventLog, NULL, errMsg);
      error = 0;
   }

   sprintf( viBuffer, ":RAD:WCDM:TGPP:BBG:ULIN:TOFF %d", iTimingOffSet ); 
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Timing offset...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
   // Sync trigger mode continuous
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Sync trigger...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:ULIN:SYNC:MODE CONT") );
   // Apply channel setup
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Apply setup...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:BBG:ULIN:APPL") );
   WaitForOPC();
   // WCDMA state ON
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Wcdma state ON...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "RAD:WCDM:TGPP:BBG:STAT ON;*OPC?") );
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Start OPC query...");
   WaitForOPC();
   Delay(5.0); // 
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "Done!");
   // Set scrambling code 
   sprintf( viBuffer, ":RAD:WCDM:TGPP:BBG:ULIN:SCR %d", iScramblingCode );
   //EELog_INEventLogLogEvent( g_hEventLog, NULL, "SCR Code...");
   esgErrChk( hpESG_cmd (g_hSignalGenerator, viBuffer) );
   
   EELog_INEventLogLogEvent (g_hEventLog, NULL, "ESG setup done.");    
   
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;") );

Error:
   if( error < 0 ) {
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }
   
   return error;
} 


// -----------------------------------------------------------------------
// Function:   SetupEsgForRxCalSignalGeneration
// Purpose:    Set ESG signal generation for RX calibration. 
//             ARB downlink signal, dual carrier TM3D32 
// Parameters: 
//  
int __declspec(dllexport) SetupEsgForRxCalSignalGeneration( )
{
   int error = 0;
   //int iReturn = 0;
   ErrMsg errMsg = {'\0'};
   ViStatus viStatus = 0;
   
   EELog_INEventLogLogEvent( g_hEventLog, NULL, 
                              "Setting ESG signal generator for RX calibration...");

   // Init multicarrier table:
   //esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK DOWN;*OPC?"));  // ????
   //WaitForOPC();
   
   // *WAI; ????
   
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;:RAD:WCDM:TGPP:ARB:LINK:DOWN:SET MCARrier"));
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL INIT,PPSCH,-2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,-2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,PPSCH,2.5E+6,0.0") );
//   esgErrChk( hpESG_cmd (g_hSignalGenerator, ":RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,2.5E+6,0.0") );
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;:RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL INIT,PPSCH,0.0,0.0") );
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;:RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:MCAR:TABL APP,TM3D32,0.0,0.0") ); 
 
   // generate a W-CDMA signal based on the current values in the W-CDMA channel table
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;:RAD:WCDM:TGPP:ARB:LINK:DOWN:SET:TABL:APPL;*OPC?") );
   WaitForOPC();
	Delay(5);
   // WCDMA ON
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;:RAD:WCDM:TGPP:ARB:STAT ON;*OPC?") );
   EELog_INEventLogLogEvent( g_hEventLog, NULL, "Start OPC query...");
   WaitForOPC();
   Delay(5);
   hpESG_ModulationSetOn( g_hSignalGenerator, VI_TRUE );
   Delay(2);
   esgErrChk( hpESG_cmd (g_hSignalGenerator, "*CLS;") );
   EELog_INEventLogLogEvent( g_hEventLog, NULL, "Done!");
Error:
   if( error < 0 ) {
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }
   
   return error;
}

// **************************************************************************  
// Select ARB file for ESG and sets up ESG     
// ************************************************************************** 
int LoadArbFile (char* pszArbFileName )
{
   ErrMsg errMsg = {'\0'};
   ViStatus viStatus = 0;
   
   int error = 0;
   char szCommand[BUF_SIZE_MEDIUM] = {'\0'};
   char szData[BUF_SIZE_MEDIUM] = {'\0'};
   // AGILENT: 
   // query contents of volatile arb memory 
   sprintf( szCommand, ":MMEM:CAT? \"WFM1:\"" );
   hpESG_cmdString_Q (g_hSignalGenerator, szCommand, 1024, szData); 

   // if waveform does not exist in volatile memory, load it from non-volatile         
   if( strstr( szData, pszArbFileName ) == 0 ) {
      sprintf( szCommand, ":MEM:COPY:NAME \"NVWFM:%s\",\"WFM1:%s\"", pszArbFileName, pszArbFileName );
      esgErrChk( hpESG_cmd( g_hSignalGenerator, szCommand ) );
      WaitForEsgOPC();
   }
 
   // Select waveform / load to arb memory
   sprintf( szCommand, ":SOUR:RAD:ARB:WAV \"WFM1:%s\"\n", pszArbFileName );
   esgErrChk( hpESG_cmd( g_hSignalGenerator, szCommand )) ;
   
   Error:
   if( error < 0 ) {
      EELog_INErrorLogLogError (g_hErrorLog, NULL, errMsg);
   }   
   return error;
}
// Function:   WaitForEsgOPC
// Purpose:    Waits until esg has completed its operation
//
int WaitForEsgOPC()
{
   ViBoolean bReady = VI_FALSE;
   
   while( bReady == VI_FALSE )
   {
      hpESG_opc_Q (g_hSignalGenerator, &bReady);
      Delay(0.25);
   }
   return 0;
}

int SetSignalGenerator (int x)
{
#if 0
   
   // ** TODO::cleanup delay!!!!!!!!!!!!!
   Delay(2.5); // some delay to let ESG level settle

   dSignalFrequency = 2135600000;

   status = hpESG_SetFrequencyCW( g_hSignalGenerator, dSignalFrequency );
   status = hpESG_SetPower( g_hSignalGenerator, 0.0, hpESG_UNIT_DBM );

   status = hpESG_ModeSetArbWaveform (g_hSignalGenerator, hpESG_ARB_WAVE_GEN_DUAL_ARB, VI_TRUE); 
   status =  hpESG_ModulationSetOn( g_hSignalGenerator, VI_TRUE );

   status = hpESG_SetPowerOn( g_hSignalGenerator, VI_TRUE );
#endif
	return 0;
}

 
/****************************************************************************
 *---------------------------- End Source File -----------------------------*
 ****************************************************************************/

